package cn.hznc.controller.service.device;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hznc.constant.CommonConstant;
import cn.hznc.constant.WarehouseConstant;
import cn.hznc.domain.dto.DeviceStatusDto;
import cn.hznc.domain.dto.WorkRangeDto;
import cn.hznc.domain.entity.ConfigurationEntity;
import cn.hznc.domain.entity.MachineToolStatus;
import cn.hznc.domain.request.device.DeviceRunAndOpenRateReq;
import cn.hznc.domain.request.device.DeviceRunningReq;
import cn.hznc.mapper.ConfigurationMapper;
import cn.hznc.repository.MachineToolStatusDailyInfoRepository;
import cn.hznc.repository.MachineToolStatusRepository;
import cn.hznc.repository.WarehouseRespository;
import cn.hznc.utils.CommonUtil;
import cn.hznc.vo.*;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author：Administrator
 * @Date：2023/10/10 11:09
 */
@Service
public class DeviceService{

    @Resource
    private WarehouseRespository warehouseRespository;

    @Resource
    private MachineToolStatusRepository machineToolStatusRepository;

    @Resource
    private MachineToolStatusDailyInfoRepository machineToolStatusDailyInfoRepository;

    @Resource
    private ConfigurationMapper configurationMapper;

    private final static String RUNNING = "running";
    private final static String FREE = "free";
    private final static String OFFLINE = "offline";
    private final static String HOLDING = "holding";

    List<DeviceRunningReq> splitDeviceRunningReqByWorkTime(DeviceRunningReq deviceRunningReq,Date workStartTime,Date workEndTime){
        List<DeviceRunningReq> deviceRunningReqs = new ArrayList<>();
        //工作开始时间
        Calendar workStartCalendar = Calendar.getInstance();
        workStartCalendar.setTime(workStartTime);
        Integer workStartHour = workStartCalendar.get(Calendar.HOUR_OF_DAY);
        Integer workStartMinute =workStartCalendar.get(Calendar.MINUTE);
        Integer workStartSecond =workStartCalendar.get(Calendar.SECOND);
        workStartCalendar.setTime(deviceRunningReq.getStartTime());
        workStartCalendar.set(Calendar.HOUR_OF_DAY, workStartHour);
        workStartCalendar.set(Calendar.MINUTE, workStartMinute);
        workStartCalendar.set(Calendar.SECOND, workStartSecond);
        Date actualworkStartTime = workStartCalendar.getTime();
        //工作结束时间
        Calendar workEndCalendar = Calendar.getInstance();
        workEndCalendar.setTime(workEndTime);
        Integer workEndtHour = workEndCalendar.get(Calendar.HOUR_OF_DAY);
        Integer workEndMinute =workEndCalendar.get(Calendar.MINUTE);
        Integer workEndSecond =workEndCalendar.get(Calendar.SECOND);
        workEndCalendar.setTime(deviceRunningReq.getStartTime());
        workEndCalendar.set(Calendar.HOUR_OF_DAY, workEndtHour);
        workEndCalendar.set(Calendar.MINUTE, workEndMinute);
        workEndCalendar.set(Calendar.SECOND, workEndSecond);
        Date actualworkEndTime = workEndCalendar.getTime();

//        Long oneDayTimeStamp = 1000*60*60*24L ;
//        Long totalTime = deviceRunningReq.getEndTime().getTime()-deviceRunningReq.getStartTime().getTime();
//        Long crossDays = totalTime/oneDayTimeStamp;

        while (actualworkStartTime.getTime() < deviceRunningReq.getEndTime().getTime()){
            DeviceRunningReq deviceRunningReqTmp = new DeviceRunningReq();
            deviceRunningReqTmp.setDeviceList(deviceRunningReq.getDeviceList());
            if(actualworkStartTime.getTime() > deviceRunningReq.getStartTime().getTime()){
                deviceRunningReqTmp.setStartTime(actualworkStartTime);
            }else{
                deviceRunningReqTmp.setStartTime(deviceRunningReq.getStartTime());
            }
            if(actualworkEndTime.getTime() > deviceRunningReq.getEndTime().getTime()){
                deviceRunningReqTmp.setEndTime(deviceRunningReq.getEndTime());
            }else{
                deviceRunningReqTmp.setEndTime(actualworkEndTime);
            }
            if(deviceRunningReqTmp.getEndTime().getTime() > deviceRunningReqTmp.getStartTime().getTime()){
                deviceRunningReqs.add(deviceRunningReqTmp);
            }
            workStartCalendar.add(Calendar.DAY_OF_MONTH,1);
            actualworkStartTime = workStartCalendar.getTime();
            workEndCalendar.add(Calendar.DAY_OF_MONTH,1);
            actualworkEndTime = workEndCalendar.getTime();
        }
        return  deviceRunningReqs;
    }

    public Object deviceRunning2(DeviceRunningReq deviceRunningReq) {
        List<DeviceRateVo> resultList = new ArrayList<>();
        if(CollectionUtil.isEmpty(deviceRunningReq.getDeviceList())){
            return resultList;
        }
        List<DeviceRunningReq> deviceRunningReqs =new ArrayList<>();

        Integer workHours = deviceRunningReq.getWorkHours();
        if(workHours != 24){
            Date workStartTime = new Date();
            Date workEndTime = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                if(workHours == 16){
                    workStartTime = sdf.parse("2023-01-01 08:00:00");
                    workEndTime = sdf.parse("2023-01-01 23:59:59");
                }else if (workHours == 8){
                    workStartTime = sdf.parse("2023-01-01 08:00:00");
                    workEndTime = sdf.parse("2023-01-01 16:00:00");
                }

            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
            deviceRunningReqs= splitDeviceRunningReqByWorkTime(deviceRunningReq,workStartTime,workEndTime);
        }
        if (!CollectionUtil.isNotEmpty(deviceRunningReqs)){
            deviceRunningReqs.add(deviceRunningReq);
        }

        for (String s : deviceRunningReq.getDeviceList()) {
            DeviceRateVo deviceRateVo = new DeviceRateVo();
            deviceRateVo.setName(s);
            //计算运行率
            Long runningTime = 0L;
            Long totalTime = 0L;
            for(DeviceRunningReq d : deviceRunningReqs){
                totalTime = totalTime + (d.getEndTime().getTime() - d.getStartTime().getTime());
                runningTime = runningTime + countTime(s, d, RUNNING , mapToSnCode(s));
            }
            deviceRateVo.setRate((runningTime * 100L) / totalTime);
            resultList.add(deviceRateVo);
        }

        return resultList;
    }

    public Object deviceRunning2Reload(DeviceRunningReq deviceRunningReq) {
        List<DeviceRateVo> resultList = new ArrayList<>();
        if(CollectionUtil.isEmpty(deviceRunningReq.getDeviceList())){
            return resultList;
        }
        List<DeviceRunningReq> deviceRunningReqs =new ArrayList<>();

        Integer workHours = deviceRunningReq.getWorkHours();
        if(workHours != 24){
            Date workStartTime = new Date();
            Date workEndTime = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                if(workHours == 16){
                    workStartTime = sdf.parse("2023-01-01 08:00:00");
                    workEndTime = sdf.parse("2023-01-01 23:59:59");
                }else if (workHours == 8){
                    workStartTime = sdf.parse("2023-01-01 08:00:00");
                    workEndTime = sdf.parse("2023-01-01 16:00:00");
                }

            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
            deviceRunningReqs= splitDeviceRunningReqByWorkTime(deviceRunningReq,workStartTime,workEndTime);
        }
        if (!CollectionUtil.isNotEmpty(deviceRunningReqs)){
            deviceRunningReqs.add(deviceRunningReq);
        }

        //连接查询机床名和snCode的映射map
        Map<String , String> machineToolNameAndSnCodeMap = new HashMap<>();
        List<String> snCodes = new ArrayList<>();
        getNameAndSnCodeMap(deviceRunningReq, machineToolNameAndSnCodeMap, snCodes);
        List<StatusVo> statusVos = machineToolStatusRepository.selectByDeviceListReload(snCodes , deviceRunningReqs);

        for (String s : deviceRunningReq.getDeviceList()) {
            DeviceRateVo deviceRateVo = new DeviceRateVo();
            deviceRateVo.setName(s);
            //根据snCode分组
            Map<String, List<StatusVo>> statusVosGroupBySnCodes = statusVos.stream().collect(Collectors.groupingBy(StatusVo::getSnCode));
            //计算运行率
            Long runningTime = 0L;
            Long totalTime = 0L;
            for(DeviceRunningReq d : deviceRunningReqs){
                totalTime = totalTime + (d.getEndTime().getTime() - d.getStartTime().getTime());
                runningTime = runningTime + countTimeReload(getStatusVosByTimePeriod(machineToolNameAndSnCodeMap, statusVosGroupBySnCodes,d ,s), d, RUNNING , mapToSnCode(s));
            }
            deviceRateVo.setRate((runningTime * 100L) / totalTime);
            resultList.add(deviceRateVo);
        }
        return resultList;
    }


    public List<DeviceRateVo> deviceOpeningReload(DeviceRunningReq deviceRunningReq) {
        List<DeviceRateVo> resultList = new ArrayList<>();
        if(CollectionUtil.isEmpty(deviceRunningReq.getDeviceList())){
            return resultList;
        }
        Map<String , String> machineToolNameAndSnCodeMap = new HashMap<>();
        List<String> snCodes = new ArrayList<>();
        getNameAndSnCodeMap(deviceRunningReq, machineToolNameAndSnCodeMap, snCodes);
        //List<String> snCodes = deviceRunningReq.getDeviceList().stream().map(this::mapToSnCode).collect(Collectors.toList());
        Long totalTime = deviceRunningReq.getEndTime().getTime()-deviceRunningReq.getStartTime().getTime();
        List<StatusVo> statusVos = machineToolStatusRepository.selectByDeviceList(snCodes , deviceRunningReq.getStartTime() , deviceRunningReq.getEndTime());
        if(CollectionUtil.isNotEmpty(statusVos)){
            Map<String, List<StatusVo>> statusVosGroupBySnCodes = statusVos.stream().collect(Collectors.groupingBy(StatusVo::getSnCode));
            deviceRunningReq.getDeviceList().forEach(s -> {
                DeviceRateVo deviceRateVo = new DeviceRateVo();
                deviceRateVo.setName(s);
                //计算停机率
                Long offlineTime = countTimeReload(getStatusVosByTimePeriod(machineToolNameAndSnCodeMap, statusVosGroupBySnCodes , deviceRunningReq ,s), deviceRunningReq , OFFLINE , mapToSnCode(s));
                deviceRateVo.setRate(((totalTime-offlineTime)*100L)/totalTime);
                resultList.add(deviceRateVo);
            });
        }else{
            dealWithEmptyStatusVos(deviceRunningReq, resultList, machineToolNameAndSnCodeMap, snCodes, "offline");
        }
        return resultList;
    }

    private void dealWithEmptyStatusVos(DeviceRunningReq deviceRunningReq, List<DeviceRateVo> resultList, Map<String, String> machineToolNameAndSnCodeMap, List<String> snCodes, String status) {
        //查询出最近的一条状态记录
        List<StatusVo> nearlyRecords = machineToolStatusRepository.selectNearlySnStatusRecord(snCodes, deviceRunningReq.getStartTime());
        Map<String, StatusVo> groupBySnCodeMap = nearlyRecords.stream().collect(Collectors.toMap(StatusVo::getSnCode , statusVo -> statusVo));
        deviceRunningReq.getDeviceList().forEach(s -> {
            //该sn距离请求开始时间最近的一条状态记录
            StatusVo snNearlyRecord = groupBySnCodeMap.getOrDefault(machineToolNameAndSnCodeMap.get(s), new StatusVo());
            DeviceRateVo deviceRateVo = new DeviceRateVo();
            deviceRateVo.setName(s);
            deviceRateVo.setRate((ObjectUtil.isNotNull(snNearlyRecord.getStatus()) && snNearlyRecord.getStatus().equals(status)) || (status.equals("offline") && StringUtils.isBlank(snNearlyRecord.getStatus())) ? 0L : 100L);
            resultList.add(deviceRateVo);
        });
    }

    public List<DeviceRateVo> deviceOpeningTask(DeviceRunningReq deviceRunningReq , Map<String , String> nameSnMap) {
        List<DeviceRateVo> resultList = new ArrayList<>();
        if(CollectionUtil.isEmpty(deviceRunningReq.getDeviceList())){
            return resultList;
        }
//        Map<String , String> machineToolNameAndSnCodeMap = new HashMap<>();
//        List<String> snCodes = new ArrayList<>();
//        getNameAndSnCodeMap(deviceRunningReq, machineToolNameAndSnCodeMap, snCodes);
        List<String> snCodes = deviceRunningReq.getDeviceList().stream().map(this::mapToSnCode).collect(Collectors.toList());
        Long totalTime = deviceRunningReq.getEndTime().getTime()-deviceRunningReq.getStartTime().getTime();
        List<StatusVo> statusVos = machineToolStatusRepository.selectByDeviceList(snCodes , deviceRunningReq.getStartTime() , deviceRunningReq.getEndTime());
        if(CollectionUtil.isNotEmpty(statusVos)){
            Map<String, List<StatusVo>> statusVosGroupBySnCodes = statusVos.stream().collect(Collectors.groupingBy(StatusVo::getSnCode));
            deviceRunningReq.getDeviceList().forEach(s -> {
                DeviceRateVo deviceRateVo = new DeviceRateVo();
                deviceRateVo.setName(s);
                //计算停机率
                Long offlineTime = countTimeReload(getStatusVosByTimePeriod(nameSnMap, statusVosGroupBySnCodes , deviceRunningReq ,s), deviceRunningReq , OFFLINE , nameSnMap.get(s));
                deviceRateVo.setRate(((totalTime-offlineTime)*100L)/totalTime);
                resultList.add(deviceRateVo);
            });
        }else{
            dealWithEmptyStatusVos(deviceRunningReq, resultList, nameSnMap, snCodes, "offline");
        }
        return resultList;
    }

    private void getNameAndSnCodeMap(DeviceRunningReq deviceRunningReq, Map<String, String> machineToolNameAndSnCodeMap, List<String> snCodes) {
        for (String machineToolName : deviceRunningReq.getDeviceList()) {
            String snCode = mapToSnCode(machineToolName);
            machineToolNameAndSnCodeMap.put(machineToolName , snCode);
            snCodes.add(snCode);
        }
    }

    @NotNull
    private static List<StatusVo> getStatusVosByTimePeriod(Map<String, String> machineToolNameAndSnCodeMap, Map<String, List<StatusVo>> statusVosGroupBySnCodes, DeviceRunningReq deviceRunningReq , String s) {
        if(CollectionUtil.isEmpty( statusVosGroupBySnCodes.getOrDefault(machineToolNameAndSnCodeMap.get(s) , new ArrayList<>()))){
            return new ArrayList<>();
        }
        return statusVosGroupBySnCodes.get(machineToolNameAndSnCodeMap.get(s))//获取对应snCode对应的状态列表
                .stream()
                .filter(statusVo -> statusVo.getCreateTime().compareTo(deviceRunningReq.getStartTime()) >=0
                        && statusVo.getCreateTime().compareTo(deviceRunningReq.getEndTime())<=0)//根据分割的时间段过滤状态列表
                .sorted(Comparator.comparing(StatusVo::getCreateTime))//按照时间大小排序 便于后续前后补偿值的计算
                .collect(Collectors.toList());
    }

    @NotNull
    private static List<StatusVo> getStatusVosByDeviceName(String deviceName, Map<String, List<StatusVo>> statusVosGroupBySnCodes) {
        if(CollectionUtil.isEmpty( statusVosGroupBySnCodes.getOrDefault(deviceName , new ArrayList<>()))){
            return new ArrayList<>();
        }
        return statusVosGroupBySnCodes.get(deviceName)//获取对应snCode对应的状态列表
                .stream()
//                .filter(statusVo -> statusVo.getCreateTime().compareTo(startTime) >=0
//                        && statusVo.getCreateTime().compareTo(endTime)<=0)//根据分割的时间段过滤状态列表
                .sorted(Comparator.comparing(StatusVo::getCreateTime))//按照时间大小排序 便于后续前后补偿值的计算
                .collect(Collectors.toList());
    }

    public List<DeviceRateVo> deviceRunning(DeviceRunningReq deviceRunningReq , Map<String , String> nameSnMap) {
        List<DeviceRateVo> resultList = new ArrayList<>();
        if(CollectionUtil.isEmpty(deviceRunningReq.getDeviceList())){
            return resultList;
        }
        //List<String> snCodes = deviceRunningReq.getDeviceList().stream().map(this::mapToSnCode).collect(Collectors.toList());
        Long totalTime = deviceRunningReq.getEndTime().getTime()-deviceRunningReq.getStartTime().getTime();
        deviceRunningReq.getDeviceList().forEach(s -> {
            DeviceRateVo deviceRateVo = new DeviceRateVo();
            deviceRateVo.setName(s);
            //计算运行率
            Long runningTime = countTime(s , deviceRunningReq , RUNNING , nameSnMap.get(s));
            deviceRateVo.setRate((runningTime*100L)/totalTime);
            resultList.add(deviceRateVo);
        });
        return resultList;
    }

    private List<StatusVo> getStatusTime(String s, Date startTime , Date endTime) {
        List<StatusVo> statusVos = machineToolStatusRepository.selectByConditionReload(mapToSnCode(s) , startTime , endTime);
        if (CollectionUtil.isNotEmpty(statusVos)) {
            for (int i = 1; i < statusVos.size(); i++) {
                if (ObjectUtil.isNotNull(statusVos.get(i - 1).getCreateTime())
                        && ObjectUtil.isNotNull(statusVos.get(i).getCreateTime()))
                    statusVos.get(i - 1).setTimeStamp(statusVos.get(i).getCreateTime().getTime() - statusVos.get(i - 1).getCreateTime().getTime());
            }
            return statusVos;
        }
        return new ArrayList<>();
    }

    private List<StatusVo> getStatusTimeReload(List<StatusVo> statusVos) {
        if (CollectionUtil.isNotEmpty(statusVos)) {
            for (int i = 1; i < statusVos.size(); i++) {
                if (ObjectUtil.isNotNull(statusVos.get(i - 1).getCreateTime())
                        && ObjectUtil.isNotNull(statusVos.get(i).getCreateTime()))
                    statusVos.get(i - 1).setTimeStamp(statusVos.get(i).getCreateTime().getTime() - statusVos.get(i - 1).getCreateTime().getTime());
            }
            return statusVos;
        }
        return new ArrayList<>();
    }

    private Long countTime(String s, DeviceRunningReq deviceRunningReq , String status , String snCode) {
        List<StatusVo> statusVos = getStatusTime(s, deviceRunningReq.getStartTime() , deviceRunningReq.getEndTime());
        if(CollectionUtil.isNotEmpty(statusVos)){
            //计算补偿值
            Long prefix = countPrefix(statusVos , status , deviceRunningReq.getStartTime() , snCode);
            Long offset = countOffset(statusVos , status , deviceRunningReq.getEndTime().getTime());
            return prefix + statusVos.stream().filter(statusVo -> statusVo.getStatus().equals(status)).mapToLong(StatusVo::getTimeStamp).sum() + offset;
        }
        MachineToolStatus machineToolStatus =  machineToolStatusRepository.selectRecentlyStatus(deviceRunningReq.getStartTime() , snCode);
        if(ObjectUtil.isNotNull(machineToolStatus.getStatus()) && machineToolStatus.getStatus().equals(status)){
            return deviceRunningReq.getEndTime().getTime() -deviceRunningReq.getStartTime().getTime();
        }
        return 0L;
    }

    private Long countTimeReload(List<StatusVo> statusVos, DeviceRunningReq deviceRunningReq , String status , String snCode) {
        if(CollectionUtil.isNotEmpty(statusVos)){
            getStatusTimeReload(statusVos);//设置time字段
            //计算补偿值
            Long prefix = countPrefix(statusVos , status , deviceRunningReq.getStartTime() , snCode);
            Long offset = countOffset(statusVos , status , deviceRunningReq.getEndTime().getTime());
            return prefix + statusVos.stream().filter(statusVo -> ObjectUtil.isNotNull(statusVo.getStatus()) && statusVo.getStatus().equals(status)).mapToLong(StatusVo::getTimeStamp).sum() + offset;
        }
        MachineToolStatus machineToolStatus =  machineToolStatusRepository.selectRecentlyStatus(deviceRunningReq.getStartTime() , snCode);
        if((status.equals("offline") && StringUtils.isBlank(machineToolStatus.getStatus())) || (ObjectUtil.isNotNull(machineToolStatus.getStatus()) && machineToolStatus.getStatus().equals(status))){
            return deviceRunningReq.getEndTime().getTime() -deviceRunningReq.getStartTime().getTime();
        }
        return 0L;
    }

    private Long countCurrentDayTime(List<StatusVo> statusVos, Date startTime , Date endTime , String status , String snCode) {
        if(CollectionUtil.isNotEmpty(statusVos)){
            getStatusTimeReload(statusVos);//设置time字段
            //计算补偿值
            Long prefix = countPrefix(statusVos , status , startTime , snCode);
            Long offset = countOffset(statusVos , status , endTime.getTime());
            return prefix + statusVos.stream().filter(statusVo -> ObjectUtil.isNotNull(statusVo.getStatus()) && statusVo.getStatus().equals(status)).mapToLong(StatusVo::getTimeStamp).sum() + offset;
        }
        MachineToolStatus machineToolStatus =  machineToolStatusRepository.selectRecentlyStatus(startTime , snCode);
        if((status.equals("offline") && StringUtils.isBlank(machineToolStatus.getStatus())) || (ObjectUtil.isNotNull(machineToolStatus.getStatus()) && machineToolStatus.getStatus().equals(status))){
            return endTime.getTime() -startTime.getTime();
        }
        return 0L;
    }

    private Long countPrefix(List<StatusVo> statusVos, String status, Date time , String snCode) {
        StatusVo statusVo = statusVos.get(0);
        MachineToolStatus machineToolStatus =  machineToolStatusRepository.selectRecentlyStatus(time , snCode);
        if(ObjectUtil.isNotNull(machineToolStatus.getStatus()) && machineToolStatus.getStatus().equals(status)){
            return statusVo.getCreateTime().getTime() - time.getTime();
        }
        return 0L;
    }

    private Long countPrefixReload(List<StatusVo> statusVos, String status, Date time , String snCode) {
        StatusVo statusVo = statusVos.get(0);
        MachineToolStatus machineToolStatus =  machineToolStatusRepository.selectRecentlyStatus(time , snCode);
        if(ObjectUtil.isNotNull(machineToolStatus) && machineToolStatus.getStatus().equals(status)){
            return statusVo.getCreateTime().getTime() - time.getTime();
        }
        return 0L;
    }

    private Long countOffset(List<StatusVo> statusVos , String status  , Long  endTime) {
        StatusVo statusVo = statusVos.get(statusVos.size()-1);
        if(ObjectUtil.isNotNull(statusVo.getStatus()) && statusVo.getStatus().equals(status)){
            Long offset = endTime - statusVo.getCreateTime().getTime();
            statusVos.remove(statusVos.size()-1);
            return offset;
        }
        return 0L;
    }

    private String mapToSnCode(String s) {
        return warehouseRespository.getSnCodeByName(s);
    }

    public Object deviceStateGantt(DeviceRunningReq deviceRunningReq) {
        Map<String, Object> retMap = new HashMap<>();
        List<MachineToolStatus> machineToolStatusList = machineToolStatusRepository.selectList(deviceRunningReq.getDeviceList() , deviceRunningReq.getStartTime() , deviceRunningReq.getEndTime());
        if(CollectionUtil.isNotEmpty(deviceRunningReq.getDeviceList())){
            deviceRunningReq.getDeviceList().forEach(s -> {
                List<MachineToolStatus> machineToolStatusList1 = machineToolStatusRepository.selectListReload(s , deviceRunningReq.getStartTime() , deviceRunningReq.getEndTime());
                if(CollectionUtil.isNotEmpty(machineToolStatusList1)){
                    machineToolStatusList.addAll(machineToolStatusList1);
                }
            });
        }
        //根据车间名称分组
        Map<String, List<MachineToolStatus>> groupByMachineToolNameMap = machineToolStatusList
                .stream().collect(Collectors.groupingBy(MachineToolStatus::getSnCode));
        //构建机床名列表
        List<String> machineToolNameList = warehouseRespository.getMachineToolNameList(WarehouseConstant.MACHINE_TOOL_CABINET);
        if (CollectionUtil.isNotEmpty(deviceRunningReq.getDeviceList())) {
            machineToolNameList = machineToolNameList.stream().filter(s -> deviceRunningReq.getDeviceList().contains(s)).collect(Collectors.toList());
        }
        List<EquipmentStatusVo> equipmentTaskStatusVos = machineToolNameList.stream().map(this::buildEquipmentTaskResultVo).collect(Collectors.toList());
        //构建返回结构
        if (CollectionUtil.isNotEmpty(groupByMachineToolNameMap)) {
            //采集到机床状态
            Set<Map.Entry<String, List<MachineToolStatus>>> entries = groupByMachineToolNameMap.entrySet();
            for (Map.Entry<String, List<MachineToolStatus>> entry : entries) {
                for (EquipmentStatusVo equipmentStatusVo : equipmentTaskStatusVos) {
                    if (equipmentStatusVo.getName().equals(warehouseRespository.getNameBySnCode(entry.getKey()))) {
                        List<MachineToolStatus> collect = entry.getValue().stream().sorted(Comparator.comparing(MachineToolStatus::getCreateTime)).collect(Collectors.toList());
                        //整合数据
                        List<MachineToolStatus> filterList = dealWithStatusList(collect);
                        dealWithTime(filterList);
                        equipmentStatusVo.setEquipmentTaskVoList(filterList);
                    }
                }
            }
            retMap.put("resultList", equipmentTaskStatusVos
                    .stream()
                    //.filter(equipmentTaskResultVo -> CollectionUtil.isNotEmpty(equipmentTaskResultVo.getEquipmentTaskVoList()))
                    .sorted(Comparator.comparingInt(allotEmployeeVo -> Integer.parseInt(allotEmployeeVo.getName().substring(1))))
                    .collect(Collectors.toList()));
        } else {
            equipmentTaskStatusVos.forEach(equipmentStatusVo -> equipmentStatusVo.setEquipmentTaskVoList(new ArrayList<>()));
            equipmentTaskStatusVos = equipmentTaskStatusVos.stream().sorted(Comparator.comparingInt(allotEmployeeVo -> Integer.parseInt(allotEmployeeVo.getName().substring(1)))).collect(Collectors.toList());
            retMap.put("resultList", equipmentTaskStatusVos);
        }
        return retMap;
    }

    public Object deviceStateGanttReload(DeviceRunningReq deviceRunningReq) {
        Map<String, Object> retMap = new HashMap<>();
        //获取机床名和snCode的印射map
        Map<String , String> machineToolNameAndSnCodeMap = new HashMap<>();
        List<String> snCodes = new ArrayList<>();
        getNameAndSnCodeMap(deviceRunningReq, machineToolNameAndSnCodeMap, snCodes);
        List<MachineToolStatus> machineToolStatusList = machineToolStatusRepository.selectListBySnCodes(snCodes , deviceRunningReq.getStartTime() , deviceRunningReq.getEndTime());
        if(CollectionUtil.isNotEmpty(deviceRunningReq.getDeviceList())){
            deviceRunningReq.getDeviceList().forEach(machineToolName -> {
                //获取该机床离请求参数开始时间最近的状态
                List<MachineToolStatus> machineToolStatusList1 = machineToolStatusRepository
                        .selectListBySnCode(machineToolNameAndSnCodeMap.getOrDefault(machineToolName ," ") , deviceRunningReq.getStartTime() , deviceRunningReq.getEndTime());
                if(CollectionUtil.isNotEmpty(machineToolStatusList1)){
                    machineToolStatusList.addAll(machineToolStatusList1);
                }
            });
        }
        //根据机床snCode分组
        Map<String, List<MachineToolStatus>> groupByMachineToolNameMap = machineToolStatusList
                .stream().collect(Collectors.groupingBy(MachineToolStatus::getSnCode));
        List<EquipmentStatusVo> equipmentTaskStatusVos = deviceRunningReq
                .getDeviceList()
                .stream()
                .map(this::buildEquipmentTaskResultVo)
                .collect(Collectors.toList());
        //构建返回结构
        if (CollectionUtil.isNotEmpty(groupByMachineToolNameMap)) {
            //采集到机床状态
            Set<Map.Entry<String, List<MachineToolStatus>>> entries = groupByMachineToolNameMap.entrySet();
            for (Map.Entry<String, List<MachineToolStatus>> entry : entries) {
                for (EquipmentStatusVo equipmentStatusVo : equipmentTaskStatusVos) {
                    //处理对应机床的状态列表
                    if (machineToolNameAndSnCodeMap.getOrDefault(equipmentStatusVo.getName() , "")
                            .equals(entry.getKey())) {
                        List<MachineToolStatus> sortByCreateTimeList = entry
                                .getValue()
                                .stream()
                                .sorted(Comparator.comparing(MachineToolStatus::getCreateTime))
                                .collect(Collectors.toList());
                        //整合数据
                        List<MachineToolStatus> filterList = dealWithStatusList(sortByCreateTimeList);
                        dealWithTime(filterList);
                        equipmentStatusVo.setEquipmentTaskVoList(filterList);
                    }
                }
            }
            retMap.put("resultList", equipmentTaskStatusVos
                    .stream()
                    //.filter(equipmentTaskResultVo -> CollectionUtil.isNotEmpty(equipmentTaskResultVo.getEquipmentTaskVoList()))
                    .sorted(Comparator.comparingInt(allotEmployeeVo -> Integer.parseInt(allotEmployeeVo.getName().substring(1))))
                    .collect(Collectors.toList()));
        } else {
            equipmentTaskStatusVos.forEach(equipmentStatusVo -> equipmentStatusVo.setEquipmentTaskVoList(new ArrayList<>()));
            equipmentTaskStatusVos = equipmentTaskStatusVos.stream().sorted(Comparator.comparingInt(allotEmployeeVo -> Integer.parseInt(allotEmployeeVo.getName().substring(1)))).collect(Collectors.toList());
            retMap.put("resultList", equipmentTaskStatusVos);
        }
        return retMap;
    }

    private List<MachineToolStatus> dealWithStatusList(List<MachineToolStatus> collect) {
        if(CollectionUtil.isEmpty(collect)){
            return new ArrayList<>();
        }
        List<MachineToolStatus> resultList = new ArrayList<>();
        String initStatus = collect.get(0).getStatus();
        resultList.add(collect.get(0));
        for (int i = 1; i < collect.size(); i++) {
            MachineToolStatus machineToolStatus = collect.get(i);
            if(!Objects.equals(machineToolStatus.getStatus(), initStatus)){
                resultList.add(machineToolStatus);
                initStatus = machineToolStatus.getStatus();
            }
        }
        return resultList;
    }

    private void dealWithTime(List<MachineToolStatus> statusVos) {
        if(CollectionUtil.isEmpty(statusVos)){
            return;
        }
        for (int i = 1; i < statusVos.size(); i++) {
            if (ObjectUtil.isNotNull(statusVos.get(i - 1).getCreateTime())
                    && ObjectUtil.isNotNull(statusVos.get(i).getCreateTime())){
                statusVos.get(i - 1).setStartTime(statusVos.get(i - 1).getCreateTime());
                statusVos.get(i - 1).setEndTime(statusVos.get(i).getCreateTime());
            }
        }
        MachineToolStatus machineToolStatus = statusVos.get(statusVos.size() - 1);
        machineToolStatus.setStartTime(machineToolStatus.getCreateTime());
        machineToolStatus.setEndTime(new Date());
    }

    private EquipmentStatusVo buildEquipmentTaskResultVo(String s) {
        EquipmentStatusVo equipmentTaskStatusVo = new EquipmentStatusVo();
        equipmentTaskStatusVo.setName(s);
        return equipmentTaskStatusVo;
    }

    public Object deviceRunningRate(DeviceRunAndOpenRateReq deviceRunAndOpenRateReq) {
        List<DeviceStatusDto> resultList = new ArrayList<>();
        //获取当天数据
        List<StatusVo>  currentStatusVoList = machineToolStatusDailyInfoRepository.selectCurrentDayData(deviceRunAndOpenRateReq);
        Map<String, List<StatusVo>> statusVosGroupBySnCodes = currentStatusVoList.stream().collect(Collectors.groupingBy(StatusVo::getSnCode));
        Map<String, Date> timeDifferenceToZero = CommonUtil.getTimeDifferenceToZero();
        Date zeroTime = timeDifferenceToZero.get("zeroTime");
        Date nowTime = timeDifferenceToZero.get("nowTime");
        List<DeviceStatusDto> currentDto = new ArrayList<>();
        Long totalTime = nowTime.getTime() - zeroTime.getTime();
        deviceRunAndOpenRateReq.getDeviceList().forEach(s -> {
            String snCode = mapToSnCode(s);
            DeviceStatusDto deviceRateVo = new DeviceStatusDto();
            deviceRateVo.setDeviceName(s);
            if(ObjectUtil.isNotNull(deviceRunAndOpenRateReq.getFlag()) && deviceRunAndOpenRateReq.getFlag()==0){
                //计算运行率
                Long runningTime = countCurrentDayTime(getStatusVosByDeviceName(s, statusVosGroupBySnCodes), zeroTime, nowTime, RUNNING , snCode);
                deviceRateVo.setRunningRate((runningTime*100L)/totalTime);
            } else if (ObjectUtil.isNotNull(deviceRunAndOpenRateReq.getFlag()) && deviceRunAndOpenRateReq.getFlag()==1) {
                //计算开机率
                Long openingTime = countCurrentDayTime(getStatusVosByDeviceName(s, statusVosGroupBySnCodes), zeroTime, nowTime, OFFLINE , snCode);
                deviceRateVo.setOpeningRate((openingTime*100L)/totalTime);
            }
            resultList.add(deviceRateVo);
        });
        //获取多余数据
        if(StringUtils.isNotBlank(deviceRunAndOpenRateReq.getTimeRange()) && !deviceRunAndOpenRateReq.getTimeRange().equals(CommonConstant.DAY) && CollectionUtil.isNotEmpty(deviceRunAndOpenRateReq.getDeviceList())){
            deviceRunAndOpenRateReq.setNum(getNumByTimeRange(deviceRunAndOpenRateReq.getTimeRange()));
            List<DeviceStatusDto> dailyDeviceStatusDtoList = machineToolStatusDailyInfoRepository.selectDailyInfoData(deviceRunAndOpenRateReq);
            for (DeviceStatusDto currentStatusDto : resultList) {
                for (DeviceStatusDto dailyStatusDto : dailyDeviceStatusDtoList) {
                    if(currentStatusDto.getDeviceName().equals(dailyStatusDto.getDeviceName())){
                        currentStatusDto.setRunningRate((currentStatusDto.getRunningRate()+dailyStatusDto.getRunningRate())/2);
                        currentStatusDto.setOpeningRate((currentStatusDto.getOpeningRate()+dailyStatusDto.getOpeningRate())/2);
                    }
                }
            }
        }
        return resultList;
    }

    public  Integer getNumByTimeRange(String timeRange) {
        Integer dayNum = 0;
        if(CommonConstant.DAY.equals(timeRange)){
            dayNum = -0;
        }else if(CommonConstant.WEEK.equals(timeRange)){
            dayNum = -7;
        }else if(CommonConstant.MONTH.equals(timeRange)){
            dayNum = -30;
        }else if(CommonConstant.HALFYEAR.equals(timeRange)){
            dayNum = -182;
        }
        return dayNum;
    }

    public Object getWorkTime() {
        QueryWrapper<ConfigurationEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("configure_key" , CommonConstant.CONFIGURE_KEY_WORK_TIME);
        ConfigurationEntity configurationEntity = configurationMapper.selectOne(wrapper);
        List<Map<String , Integer>> resultList = new ArrayList<>();
        if(StringUtils.isNotBlank(configurationEntity.getConfigureValue())){
            List<WorkRangeDto> workRangeDtoList = JSONArray.parseArray(configurationEntity.getConfigureValue(), WorkRangeDto.class);
            if(CollectionUtil.isNotEmpty(workRangeDtoList)){
                workRangeDtoList.forEach(workRangeDto -> {
                    List<String> strings = Arrays.asList(workRangeDto.getTimeRange().split("-"));
                    List<Integer> collect = strings
                            .stream()
                            .map(Integer::valueOf)
                            .sorted(Comparator.comparingInt(Integer::intValue)).collect(Collectors.toList());
                    Map<String , Integer> map = new HashMap<>();
                    if(CollectionUtil.isNotEmpty(strings)){
                        map.put("startValue" , collect.get(0));
                        map.put("endValue" , collect.get(1));
                    }
                    resultList.add(map);
                });
            }
            return resultList;
        }
        return resultList;
    }
}
